home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-01-14 | 27.7 KB | 790 lines | [TEXT/CWIE] |
- /* -----------------------------------------------------------------------------------
- -----------------------------------------------------------------------------------
- SWLightingSquares.c
-
- by Brian Roddy
-
- 5/20/97
-
-
- ** N.B. These functions are still experimental. They work fine, but the public API
- needs work to achieve better effects and uses.
-
-
- These routines are for an alternative style of getting lighting effects. It's
- main function is a Screen Blitting procedures that takes the offscreen work area
- and colors it as it copies it on screen. Thus the parts copied on screen can
- be made darker or lighter or a little reddish, etc.
-
- To support a feeling of lights, we divide the screen into a map of tiny squares
- and associate a color and a level with each square. As we blit onto the screen,
- we use this map to color the image. The result is that the screen image looks
- nicely colorized. Imagine each square having a colored gel placed over top of
- it.
-
- The smaller the squares in our map, the finer the grain of lighting but the greater
- the overhead. More space and speed are required. We also provide routines for setting
- and managing this lighting map, including setting light levels and combining
- lights (so blue lights and yellow lights will become greenish lights as they overlap).
-
- These functions make use of the translucency table functions found in
- "SWTranslucentBlitters.c" and therefore that file needs to be present for this to
- work.
-
- Use SWInitializeLightingSquares(spriteWorldPtr, 8); to initialize the use of squares.
- 8 in this case is the size of the squares in pixels.
-
- Use:
- SWSetLightingSquare(spriteWorldPtr, col, row,
- color, opacity,
- relativeP, makeDirtyP);
- to set a cell's value. Opacity is the translucency levels (as in the translucent blitters).
- relativeP is a boolean specifying whether to set the color and level directly or to blend
- it together with what is already in the cell. makeDirtyP forces sprite world to redraw
- that cell on the screen during the next draw loop.
-
- Use:
- SWLightUpArea (spriteWorldPtr, col, row,
- color, level
- bigLightP);
- to light up an area around a cell. This is good for spotlights. bigLightP makes the light
- really big. Note that this just calls SWSetLightingSquare repeatedly.
-
- SWDarkenLightingSquares (spriteWorldPtr); will blend black into every square in the
- grid to darken everything. This is a good example of how to achieve a lighting effect
- with these squares.
-
- Use SWExitLightingSquares (); to free up the tables when quitting.
-
- The Lit Breakout Demo is an example of how to use these functions in an app.
-
-
- -------------------------------------------------------------------------------------
- Implementation Notes:
-
- The engine for all of this is the code for blitting Tinted Rects in 8 bit or in 16 bit
- mode. There are straight C versions as well as versions that use optimize PowerPC
- assembly.
-
- This source code is available for free use.
- -----------------------------------------------------------------------------------
- ----------------------------------------------------------------------------------- */
-
- ///--------------------------------------------------------------------------------------
- // Includes
- ///--------------------------------------------------------------------------------------
-
- #include "SWTranslucentBlitters.h"
- #include "SWLightingSquares.h"
- #include <SWGameUtils.h>
-
- unsigned long *gLitSquareColorTable;
- unsigned long *gLitSquareLevelTable;
- int gLightingSquareRows, gLightingSquareColumns;
- int SWLitSquareSize = 8;
-
- unsigned long gBlackColor;
-
- #pragma mark ----------- Public API -------------
- SW_FUNC OSErr SWInitializeLightingSquares (SpriteWorldPtr spriteWorldP,
- int squareSize) {
- long arraySize;
- OSErr err = noErr;
-
- SWLitSquareSize = squareSize;
- gLightingSquareColumns = ((spriteWorldP->windRect.right - spriteWorldP->windRect.left) / SWLitSquareSize) + 1;
- gLightingSquareRows = ((spriteWorldP->windRect.bottom - spriteWorldP->windRect.top) / SWLitSquareSize) + 1;
-
- SWExitLightingSquares ();
-
- if (err == noErr) {
- if (spriteWorldP->pixelDepth == 8) {
- SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie8BitLitRectDrawProc);
- CreateCLUTTable();
- gBlackColor = ColorToIndex(0,0,0);
- } else if (spriteWorldP->pixelDepth == 16) {
- SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie16BitLitRectDrawProc);
- gBlackColor = 0x0000;
-
- }
- else
- err = kWrongDepthErr;
- }
-
- if (err == noErr) {
- arraySize = gLightingSquareColumns * gLightingSquareRows * sizeof(unsigned long);
- gLitSquareColorTable = (unsigned long *)NewPtr(arraySize);
- err = MemError();
- }
-
- if (err == noErr) {
- arraySize = gLightingSquareColumns * gLightingSquareRows * sizeof(unsigned long);
- gLitSquareLevelTable = (unsigned long *)NewPtr(arraySize);
- err = MemError();
- }
-
- return err;
- }
-
- SW_FUNC void SWExitLightingSquares ()
- {
- // Only do this if we've created a table.
- if (gLitSquareColorTable != NULL) DisposePtr((Ptr)gLitSquareColorTable);
- if (gLitSquareLevelTable != NULL) DisposePtr((Ptr)gLitSquareLevelTable);
- }
-
-
-
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
- /// Table Management Functions
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWSetLightingSquare(SpriteWorldPtr swp, int col, int row,
- unsigned long color, unsigned long level,
- Boolean relative, Boolean makeDirty) {
- long index, curColor, curLevel, newColor, newLevel;
- Rect changedRect;
-
- // Bounds Checking
- if (! ((row < 0) ||
- (col < 0) ||
- (row >= gLightingSquareRows) ||
- (col >= gLightingSquareColumns))) {
-
- int maxLevel;
- if (swp->pixelDepth == 8)
- maxLevel = gNumberOf8BitTranslucencyLevels;
- else
- maxLevel = 32;
- if (level < 0) level = 0;
- if (level >= maxLevel) level = (maxLevel - 1);
-
- // Compute the data structure
- index = ((row * gLightingSquareColumns) + col);
- curColor = gLitSquareColorTable[index];
- curLevel = gLitSquareLevelTable[index];
-
- if (relative) {
- if (swp->pixelDepth == 8) {
- newColor = Blend8BitPixels(level, curColor, color);
- } else {
- newColor = Blend16BitPixels(level, curColor, color);
- }
-
- if (newColor == curColor)
- newColor = color;
-
- newLevel = (curLevel + level) / 2;
- if (newLevel == curLevel)
- newLevel = level;
-
- } else {
- newColor = color;
- newLevel = level;
- }
-
- // And if the value is different
- if ((curColor != newColor) ||
- (curLevel != newLevel)) {
-
- // Update the data structure
- gLitSquareColorTable[index] = newColor;
- gLitSquareLevelTable[index] = newLevel;
-
- if (makeDirty) {
- // And tell spriteworld that the square is dirty
- changedRect.top = row * SWLitSquareSize;
- changedRect.bottom = ((row + 1) * SWLitSquareSize);
- changedRect.left = col * SWLitSquareSize;
- changedRect.right = ((col + 1) * SWLitSquareSize);
- SWFlagRectAsChanged(swp, &changedRect);
- }
- }
- }
- }
-
- ///--------------------------------------------------------------------------------------
- ///---- SWDarkenLightingSquares.
- ///
- /// A utility function to do light fading over time.
-
- SW_FUNC void SWDarkenLightingSquares (SpriteWorldPtr swp)
- {
- int row, col, index = 0;
- int maxLevel;
-
- if (swp->pixelDepth == 8)
- maxLevel = gNumberOf8BitTranslucencyLevels - 1;
- else
- maxLevel = 30;
-
- for (row = 0; row < gLightingSquareRows; row++)
- for (col = 0; col < gLightingSquareColumns; col++) {
- if ((gLitSquareColorTable[index] != gBlackColor) ||
- (gLitSquareLevelTable[index] != maxLevel)) {
- int index = ((row * gLightingSquareColumns) + col);
- int curLevel = gLitSquareLevelTable[index];
-
- SWSetLightingSquare(swp, col, row, gBlackColor, maxLevel, (curLevel != maxLevel), true);
- }
- index++;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWLightUpArea (
- SpriteWorldPtr swp,
- int col,
- int row,
- unsigned long lightColor,
- int lightLevel,
- Boolean BigLight) {
-
- // Light up the tiles around the sprite. Light up the center sprite and
- // adjacent ones really bright, Light up the four diagonally adjacent ones
- // fairly bright.
-
- // Calculate the light levels
- int lightLevelBorder = lightLevel;
- int lightLevelMiddle = lightLevelBorder; // + RandomNumber(2);
-
- Boolean blendIt = true;
-
- // and light them up
- SWSetLightingSquare(swp, col - 1, row - 1, lightColor, lightLevelBorder, blendIt, true);
- SWSetLightingSquare(swp, col , row - 1, lightColor, lightLevelMiddle, blendIt, true);
- SWSetLightingSquare(swp, col + 1, row - 1, lightColor, lightLevelBorder, blendIt, true);
- SWSetLightingSquare(swp, col - 1, row , lightColor, lightLevelMiddle, blendIt, true);
- SWSetLightingSquare(swp, col , row , lightColor, lightLevelMiddle, blendIt, true);
- SWSetLightingSquare(swp, col + 1, row , lightColor, lightLevelMiddle, blendIt, true);
- SWSetLightingSquare(swp, col - 1, row + 1, lightColor, lightLevelBorder, blendIt, true);
- SWSetLightingSquare(swp, col , row + 1, lightColor, lightLevelMiddle, blendIt, true);
- SWSetLightingSquare(swp, col + 1, row + 1, lightColor, lightLevelBorder, blendIt, true);
-
- if (BigLight)
- { /// If BigLight is true then we make a really big light that
- /// lights up a 5x5 area of tiles rather than 3x3
- int lightLevelEdgeCorner = lightLevelBorder + 2;
- int lightLevelEdgeNearCorner = lightLevelBorder + 1;
- int lightLevelEdge = lightLevelBorder + 1;
-
- SWSetLightingSquare(swp, col - 2, row - 2, lightColor, lightLevelEdgeCorner, blendIt, true);
- SWSetLightingSquare(swp, col + 2, row - 2, lightColor, lightLevelEdgeCorner, blendIt, true);
- SWSetLightingSquare(swp, col - 2, row + 2, lightColor, lightLevelEdgeCorner, blendIt, true);
- SWSetLightingSquare(swp, col + 2, row + 2, lightColor, lightLevelEdgeCorner, blendIt, true);
- SWSetLightingSquare(swp, col - 1, row - 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col , row - 2, lightColor, lightLevelEdge, blendIt, true);
- SWSetLightingSquare(swp, col + 1, row - 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col - 1, row + 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col , row + 2, lightColor, lightLevelEdge, blendIt, true);
- SWSetLightingSquare(swp, col + 1, row + 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col - 2, row - 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col - 2, row , lightColor, lightLevelEdge, blendIt, true);
- SWSetLightingSquare(swp, col - 2, row + 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col + 2, row - 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- SWSetLightingSquare(swp, col + 2, row , lightColor, lightLevelEdge, blendIt, true);
- SWSetLightingSquare(swp, col + 2, row + 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
- }
-
- }
-
-
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
- /// The Blitting Functions
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
-
- extern SInt8 gSWmmuMode;
-
- #pragma mark ----------- 8 Bit Screen Draw Function -------------
- ///--------------------------------------------------------------------------------------
- // BlitPixie8BitRectDrawProc
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void BlitPixie8BitLitRectDrawProc(
- FramePtr srcFrameP,
- FramePtr dstFrameP,
- Rect* srcRect,
- Rect* dstRect
- )
- {
- Rect srcBlitRect = *srcRect;
- Rect dstBlitRect = *dstRect;
- unsigned long numBytesPerRow;
- register unsigned char *tableAtLevelAndIndex;
- int startRow, endRow, startCol, endCol;
- int row, col, index;
- Rect curSrcBlitRect, curDstBlitRect;
-
- SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
- SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
- SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
-
- BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
- START_32_BIT_MODE
-
- startRow = dstBlitRect.top / SWLitSquareSize;
- startCol = dstBlitRect.left / SWLitSquareSize;
- endRow = (dstBlitRect.bottom / SWLitSquareSize) + 1 ;
- endCol = (dstBlitRect.right / SWLitSquareSize) + 1;
-
- for (row = startRow; row <= endRow; row++) {
- for (col = startCol; col <= endCol; col++) {
- index = ((row * gLightingSquareColumns) + col);
- tableAtLevelAndIndex = &g8BitTranslucencyTable[(gLitSquareLevelTable[index] << 16) | (gLitSquareColorTable[index] << 8)];
-
- curSrcBlitRect.top = row * SWLitSquareSize;
- curSrcBlitRect.bottom = curSrcBlitRect.top + SWLitSquareSize;
- curSrcBlitRect.left = col * SWLitSquareSize;
- curSrcBlitRect.right = curSrcBlitRect.left + SWLitSquareSize;
- curDstBlitRect.top = row * SWLitSquareSize;
- curDstBlitRect.bottom = curDstBlitRect.top + SWLitSquareSize;
- curDstBlitRect.left = col * SWLitSquareSize;
- curDstBlitRect.right = curDstBlitRect.left + SWLitSquareSize;
-
- SectRect(&dstBlitRect, &curDstBlitRect, &curDstBlitRect);
- SectRect(&srcBlitRect, &curSrcBlitRect, &curSrcBlitRect);
-
- // calculate the number of bytes in each row to be copied
- numBytesPerRow = (curDstBlitRect.right - curDstBlitRect.left);
-
- BlitPixieLit8Bit(
- // calculate the address of the first byte of the source
- (PixelChunkPtr)(srcFrameP->frameBaseAddr +
- (srcFrameP->scanLinePtrArray[curSrcBlitRect.top - srcFrameP->frameRect.top]) +
- curSrcBlitRect.left),
-
- // calculate the address of the first byte of the destination
- (PixelChunkPtr)(dstFrameP->frameBaseAddr +
- (dstFrameP->scanLinePtrArray[curDstBlitRect.top]) + curDstBlitRect.left),
-
- // calculate the number of rows to blit
- curDstBlitRect.bottom - curDstBlitRect.top,
-
- // number of bytes in a row (also the number of pixels to be copied)
- numBytesPerRow,
-
- srcFrameP->frameRowBytes,
- dstFrameP->frameRowBytes,
- tableAtLevelAndIndex
- );
- }
- }
-
- END_32_BIT_MODE
- }
-
-
- ///--------------------------------------------------------------------------------------
- // LightingConvertChar
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC unsigned char SWInline LightingConvertChar (
- register unsigned char srcPixel,
- register unsigned char *tableAtLevelAndIndex) {
-
- // Easy, just the pixel in the table
- return tableAtLevelAndIndex[srcPixel];
- }
-
-
- ///--------------------------------------------------------------------------------------
- // LightingConvertShort
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC unsigned short LightingConvertShort (
- register unsigned short srcPixel,
- register unsigned char *tableAtLevelAndIndex) {
-
- register unsigned long colorValue;
- register unsigned long result = 0L;
-
- colorValue = tableAtLevelAndIndex[srcPixel >> 8];
- result = colorValue << 8;
- colorValue = tableAtLevelAndIndex[(srcPixel & 0x00FF)];
- result = colorValue | result;
- return result;
- }
-
- #if USE_PPC_ASSEMBLY && __MWERKS__ >= 0x1800 // Only compiles under CW Pro
-
- ///--------------------------------------------------------------------------------------
- // LightingConvertLong
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC unsigned long LightingConvertLong (
- register unsigned long srcPixel,
- register unsigned char *tableAtLevelAndIndex) {
-
- register unsigned long colorValue;
- register unsigned long result;
-
- colorValue = tableAtLevelAndIndex[srcPixel >> 24]; // look up the colored pixel
- result = colorValue << 24; // and shift it back into place as our high end pixel
- colorValue = tableAtLevelAndIndex[((srcPixel >> 16) & 0x000000FF)];
- __rlwimi( result, colorValue, 16, 8, 15 );
- colorValue = tableAtLevelAndIndex[((srcPixel >> 8) & 0x000000FF)];
- __rlwimi( result, colorValue, 8, 16, 23 );
- colorValue = tableAtLevelAndIndex[(srcPixel & 0x000000FF)];
- __rlwimi( result, colorValue, 0, 24, 31 );
-
- // return the four pixels we've computed
- return result;
- }
-
- #else /* USE_PPC_ASSEMBLY && __MWERKS__ >= 0x1800 */
-
- ///--------------------------------------------------------------------------------------
- // LightingConvertLong
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC unsigned long SWInline LightingConvertLong (
- register unsigned long srcPixel,
- register unsigned char *tableAtLevelAndIndex) {
-
- register unsigned long colorValue;
- register unsigned long result = 0L;
-
- colorValue = tableAtLevelAndIndex[srcPixel >> 24]; // look up the colored pixel
- result = colorValue << 24; // and shift it back into place as our high end pixel
- colorValue = tableAtLevelAndIndex[((srcPixel >> 16) & 0x000000FF)];
- result = (colorValue << 16) | result;
- colorValue = tableAtLevelAndIndex[((srcPixel >> 8) & 0x000000FF)];
- result = (colorValue << 8) | result;
- colorValue = tableAtLevelAndIndex[(srcPixel & 0x000000FF)];
- result = colorValue | result;
-
- // return the four pixels we've computed
- return result;
- }
-
- #endif /* USE_PPC_ASSEMBLY */
-
- ///--------------------------------------------------------------------------------------
- // BlitPixieLit8Bit
- ///--------------------------------------------------------------------------------------
-
-
- SW_FUNC void BlitPixieLit8Bit(
- PixelChunkPtr srcPixelP,
- PixelChunkPtr dstPixelP,
- register unsigned long rowsToCopy,
- register unsigned long numBytesPerRow,
- register unsigned long srcOffset,
- register unsigned long dstOffset,
- register unsigned char *tableAtLevelAndIndex)
- {
- register long index;
- register PixelChunkPtr startSrcPixelP;
- register PixelChunkPtr startDstPixelP;
-
-
- startSrcPixelP = srcPixelP;
- startDstPixelP = dstPixelP;
-
- while (rowsToCopy--)
- {
- register fourblits = (numBytesPerRow >> 2);
-
- srcPixelP = startSrcPixelP;
- dstPixelP = startDstPixelP;
-
- for (index = 0; index < fourblits; index++) {
- dstPixelP[index] = LightingConvertLong(srcPixelP[index], tableAtLevelAndIndex);
- }
-
- srcPixelP += fourblits;
- dstPixelP += fourblits;
-
- #ifdef MWERKS
- if (numBytesPerRow & 0x2)
- *((unsigned short *) dstPixelP)++ = LightingConvertShort(*((unsigned short *) srcPixelP)++, tableAtLevelAndIndex);
- if (numBytesPerRow & 0x1)
- *((unsigned char *) dstPixelP)++ = LightingConvertChar(*((unsigned char *) srcPixelP)++, tableAtLevelAndIndex);
- #else
- if (numBytesPerRow & 0x2)
- {
- // Work around Think C's inability to do simple typecasting - Vern
- *(unsigned short *)dstPixelP = LightingConvertShort(*(unsigned short *)srcPixelP, tableAtLevelAndIndex);
- srcPixelP = (PixelChunkPtr)(((unsigned short *)srcPixelP) + 1);
- dstPixelP = (PixelChunkPtr)(((unsigned short *)dstPixelP) + 1);
- }
- if (numBytesPerRow & 0x1)
- {
- *(unsigned char *)dstPixelP = LightingConvertChar(*(unsigned char *)srcPixelP, tableAtLevelAndIndex);
- srcPixelP = (PixelChunkPtr)(((unsigned char *)srcPixelP) + 1);
- dstPixelP = (PixelChunkPtr)(((unsigned char *)dstPixelP) + 1);
- }
- #endif
-
- // bump to next row
- #ifdef MWERKS
- (char *)startSrcPixelP += srcOffset;
- (char *)startDstPixelP += dstOffset;
- #else
- startSrcPixelP = (PixelChunkPtr)(((char *)startSrcPixelP) + srcOffset);
- startDstPixelP = (PixelChunkPtr)(((char *)startDstPixelP) + dstOffset);
- #endif
- }
- }
-
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
- ///--------------------------------------------------------------------------------------
- /// 16 Bit Versions
-
- #pragma mark ----------- 16 Bit Screen Draw Function -------------
- ///--------------------------------------------------------------------------------------
- // BlitPixie16BitRectDrawProc
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void BlitPixie16BitLitRectDrawProc(
- FramePtr srcFrameP,
- FramePtr dstFrameP,
- Rect* srcRect,
- Rect* dstRect
- )
- {
- Rect srcBlitRect = *srcRect;
- Rect dstBlitRect = *dstRect;
- unsigned long numBytesPerRow;
- int startRow, endRow, startCol, endCol;
- int row, col, index;
- Rect curSrcBlitRect, curDstBlitRect;
-
- SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
- SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 16);
- SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 16);
-
- BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);
- START_32_BIT_MODE
-
- startRow = dstBlitRect.top / SWLitSquareSize;
- startCol = dstBlitRect.left / SWLitSquareSize;
- endRow = (dstBlitRect.bottom / SWLitSquareSize) + 1 ;
- endCol = (dstBlitRect.right / SWLitSquareSize) + 1;
-
- for (row = startRow; row <= endRow; row++) {
- for (col = startCol; col <= endCol; col++) {
- index = ((row * gLightingSquareColumns) + col);
-
- curSrcBlitRect.top = row * SWLitSquareSize;
- curSrcBlitRect.bottom = curSrcBlitRect.top + SWLitSquareSize;
- curSrcBlitRect.left = col * SWLitSquareSize;
- curSrcBlitRect.right = curSrcBlitRect.left + SWLitSquareSize;
- curDstBlitRect.top = row * SWLitSquareSize;
- curDstBlitRect.bottom = curDstBlitRect.top + SWLitSquareSize;
- curDstBlitRect.left = col * SWLitSquareSize;
- curDstBlitRect.right = curDstBlitRect.left + SWLitSquareSize;
-
- SectRect(&dstBlitRect, &curDstBlitRect, &curDstBlitRect);
- SectRect(&srcBlitRect, &curSrcBlitRect, &curSrcBlitRect);
-
- numBytesPerRow = curDstBlitRect.right - curDstBlitRect.left;
-
- if (numBytesPerRow > 0) // don't draw when the intersection is null...
- BlitPixieLit16Bit(
- // calculate the address of the first byte of the source
- (unsigned short *)(srcFrameP->frameBaseAddr +
- (srcFrameP->scanLinePtrArray[curSrcBlitRect.top - srcFrameP->frameRect.top]) +
- (curSrcBlitRect.left << 1)),
-
- // calculate the address of the first byte of the destination
- (unsigned short *)(dstFrameP->frameBaseAddr +
- (dstFrameP->scanLinePtrArray[curDstBlitRect.top]) +
- (curDstBlitRect.left << 1)),
-
- // number of bytes in a row (also the number of pixels to be copied)
- numBytesPerRow,
- curDstBlitRect.bottom - curDstBlitRect.top,
-
- srcFrameP->frameRowBytes,
- dstFrameP->frameRowBytes,
- gLitSquareColorTable[index],
- gLitSquareLevelTable[index]
- );
- }
- }
-
- END_32_BIT_MODE
- }
-
-
- #if USE_PPC_ASSEMBLY
-
- // Some defines to make this easier to read
- #define lookup_offset1 alpha
- #define lookup_offset2 r11
- #define lookup_offset3 r12
- #define tablePointer r13
- #define tmp1 r0
- #define tmp2 r31
- #define tmp3 r30
-
- void asm BlitPixieLit16Bit(
- register unsigned short *srcPtr,
- register unsigned short *dstPtr,
- register unsigned long width,
- register unsigned long height,
- register unsigned long srcRowBytes,
- register unsigned long dstRowBytes,
- register unsigned long color,
- register unsigned long alpha)
- {
- stw tmp2,-4(SP) //store temp vars on the stack
- stw tmp3,-8(SP)
- stw lookup_offset2,-12(SP)
- stw lookup_offset3,-16(SP)
- stw tablePointer,-20(SP)
-
- // Load a register with a pointer to our table
- lwz tablePointer, g16BitTranslucencyTable(RTOC)
- lwz tablePointer, 0(tablePointer)
-
- // We need to make the rowBytes be rowBytes - width because we are using
- // preincrements when getting and setting the pixels
- add tmp1, width, width //adjust for pixels being 2 bytes long
- sub srcRowBytes,srcRowBytes,tmp1 //calculateoffsets to the next row
- sub dstRowBytes,dstRowBytes,tmp1
-
- //adjust the pointers so we can use pre-increments
- subi srcPtr,srcPtr,2
- subi dstPtr,dstPtr,2
-
- // Set up the offsets into the blending table for each of our R, G, and B lookups
- // by setting the high order five bits to the alpha color
- // Note that these high order bits never get changed as we
- // work on our pixels, so the alpha (translucency level)
- // stays the same
- rlwinm lookup_offset3,alpha,10,17,21
- mr lookup_offset2,lookup_offset3
- mr lookup_offset1,lookup_offset3
-
- rlwimi lookup_offset3, color, 5, 22, 26 //blue channel source
- rlwimi lookup_offset2, color, 0, 22, 26 //green channel source
- rlwimi lookup_offset1, color, 27, 22, 26 //red channel source
-
-
- @yloop
- mtctr width //set the ctr to so we copy do WIDTH number of pixels
-
- @xloop
- lhzu tmp1,2(srcPtr) //load the source and destination colour
-
- rlwimi lookup_offset3,tmp1,0,27,31 //blue channel destination
- rlwimi lookup_offset2,tmp1,27,27,31 //green channel destination
- rlwimi lookup_offset1,tmp1,22,27,31 //red channel destination
-
- lbzx tmp3,tablePointer,lookup_offset3 //load blended blue channel
- lbzx tmp2,tablePointer,lookup_offset2 //load blended green channel
- lbzx tmp1,tablePointer,lookup_offset1 //load blended red channel
-
- rlwimi tmp3,tmp2,5,22,26 //insert green channel into result
- rlwimi tmp3,tmp1,10,17,21 //insert red channel into result
-
- sthu tmp3,2(dstPtr) //store result
-
- @endOfBlitXLoop
- bdnz @xloop // decrement the ctr and see if we're done
-
- // Now we move the pointers forward to the next row
- add srcPtr,srcPtr,srcRowBytes
- add dstPtr,dstPtr,dstRowBytes
-
- //and if we haven't finished, continue
- subi height,height,1
- cmpwi height,0
- bne @yloop
-
- lwz tmp2,-4(SP) //clean up, restore registers we've been using
- lwz tmp3,-8(SP)
- lwz lookup_offset2,-12(SP)
- lwz lookup_offset3,-16(SP)
- lwz tablePointer,-20(SP)
-
- blr
-
- }
-
- #undef lookup_offset1
- #undef lookup_offset2
- #undef lookup_offset3
- #undef tmp1
- #undef tmp2
- #undef tmp3
- #undef height
- #undef width
-
- #else /* USE_PPC_ASSEMBLY */
-
- // Here is a C version of the above function.
- // it's about 20% slower than the assembly one.
-
- // Note: don't declare the args to this function as "register". If you do, then
- // it won't compile properly for the 68K.
-
- void BlitPixieLit16Bit (
- unsigned short *srcPtr,
- unsigned short *dstPtr,
- unsigned long width,
- unsigned long height,
- unsigned long srcRowBytes,
- unsigned long dstRowBytes,
- unsigned long color,
- unsigned long alpha) {
-
- int xx, yy;
- unsigned long lookup_offset_blue, lookup_offset_green, lookup_offset_red;
- unsigned long final_red, final_green, final_result;
- short curSource;
-
- srcRowBytes -= width * 2;
- dstRowBytes -= width * 2;
-
- lookup_offset_blue = lookup_offset_green = lookup_offset_red = alpha << 10;
- lookup_offset_blue |= (color << 5) & 0x03E0;
- lookup_offset_green |= color & 0x03E0;
- lookup_offset_red |= (color >> 5) & 0x03E0;
-
- for (yy = 0; yy < height; yy++) {
- for (xx = 0; xx < width; xx++) {
- curSource = *srcPtr++;
-
- lookup_offset_blue &= 0xFFE0;
- lookup_offset_green &= 0xFFE0;
- lookup_offset_red &= 0xFFE0;
-
- lookup_offset_blue |= curSource & 0x001F;
- lookup_offset_green |= (curSource >> 5) & 0x001F;
- lookup_offset_red |= (curSource >> 10) & 0x001F;
-
- final_red = g16BitTranslucencyTable[lookup_offset_red];
- final_green = g16BitTranslucencyTable[lookup_offset_green];
- final_result = g16BitTranslucencyTable[lookup_offset_blue];
-
- final_result |= final_green << 5;
- final_result |= final_red << 10;
-
- *dstPtr++ = final_result;
- }
-
- #ifdef MWERKS
- (char *)srcPtr += srcRowBytes;
- (char *)dstPtr += dstRowBytes;
- #else
- srcPtr = (unsigned short *)(((char *)srcPtr) + srcRowBytes);
- dstPtr = (unsigned short *)(((char *)dstPtr) + dstRowBytes);
- #endif
- }
-
- }
- #endif /* USE_PPC_ASSEMBLY */
-